package segmented_control.widget.custom.ohos.com.segmentedcontrol.custom_segment;


import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;

import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;

import ohos.multimodalinput.event.TouchEvent;

import org.jetbrains.annotations.NotNull;

import segmented_control.widget.custom.ohos.com.segmentedcontrol.ArgbEvaluator;
import segmented_control.widget.custom.ohos.com.segmentedcontrol.ColorEntity;
import segmented_control.widget.custom.ohos.com.segmentedcontrol.ResourceTable;
import segmented_control.widget.custom.ohos.com.segmentedcontrol.TouchEventCompact;
import segmented_control.widget.custom.ohos.com.segmentedcontrol.item_row_column.SegmentViewHolder;

import java.util.concurrent.atomic.AtomicInteger;

import static segmented_control.widget.custom.ohos.com.segmentedcontrol.utils.Utils.*;

/**
 * Created by Robert Apikyan on 9/8/2017.
 */

public class SegmentViewHolderImpl extends SegmentViewHolder<CharSequence> {
    /**
     * itemTV
     */
    private Text itemTV;
    /**
     * radius
     */
    private float[] radius;
    /**
     * compact
     */
    private TouchEventCompact compact;

    @SuppressWarnings("FieldCanBeLocal")
    private final Component.TouchEventListener segmentTouchListener = new Component.TouchEventListener() {
        @Override
        public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
            compact.correctY(touchEvent);
            if (isSelected()) {
                return false;
            }
            switch (touchEvent.getAction()) {
                case TouchEvent.PRIMARY_POINT_DOWN:
                case TouchEvent.POINT_MOVE:
                    setBackground(getFocusedBackground());
                    return true;
                case TouchEvent.PRIMARY_POINT_UP:
                case TouchEvent.CANCEL:
                    if (!isInBounds(touchEvent.getPointerPosition(0).getX(), touchEvent.getPointerPosition(0).getY(), touchEvent.getPointerScreenPosition(0).getX(), touchEvent.getPointerScreenPosition(0).getY(),
                            getSectionView().getEstimatedWidth(), getSectionView().getEstimatedHeight())) {
                        setBackground(isSelected() ? getSelectedBackground() : getUnSelectedBackground());
                    }
                    break;
            }
            return false;
        }
    };

    public SegmentViewHolderImpl(@NotNull Component sectionView) {
        super(sectionView);
        compact = new TouchEventCompact();
        Component component = sectionView.findComponentById(ResourceTable.Id_item_segment_tv);
        if (component instanceof Text) {
            itemTV = (Text) component;
        }
        sectionView.setTouchEventListener(segmentTouchListener);
    }

    @Override
    protected void onSegmentBind(CharSequence segmentData) {
        initScreenLocation();
        itemTV.setText((String) segmentData);
        if (isRadiusForEverySegment()) {
            radius = createRadius(getTopLeftRadius(), getTopRightRadius(), getBottomRightRadius(), getBottomLeftRadius());
        } else {
            radius = defineRadiusForPosition(getAbsolutePosition(), getColumnCount(), getCurrentSize(), getTopLeftRadius(), getTopRightRadius(), getBottomRightRadius(), getBottomLeftRadius());
        }
        setSectionDecorationSelected(false, false);
        itemTV.setTextSize(getTextSize());
        itemTV.setPadding(getTextHorizontalPadding(), getTextVerticalPadding(), getTextHorizontalPadding(), getTextVerticalPadding());
        itemTV.setMarginLeft(getSegmentHorizontalMargin());
        itemTV.setMarginTop(getSegmentVerticalMargin());
        itemTV.setMarginRight(getSegmentHorizontalMargin());
        itemTV.setMarginBottom(getSegmentHorizontalMargin());
    }

    private void initScreenLocation() {
        getSectionView().getLocationOnScreen();
    }

    @Override
    public void onSegmentSelected(boolean isSelected, boolean isReselected) {
        super.onSegmentSelected(isSelected, isReselected);
        setSectionDecorationSelected(isSelected, isReselected);
    }

    private ShapeElement getSelectedBackground() {
        return getBackground(getStrokeWidth(), getSelectedStrokeColor(), getSelectBackgroundColor(), radius);
    }

    private ShapeElement getUnSelectedBackground() {
        return getBackground(getStrokeWidth(), getUnSelectedStrokeColor(), getUnSelectedBackgroundColor(), radius);
    }

    private ShapeElement getFocusedBackground() {
        return getBackground(getStrokeWidth(), isSelected() ? getSelectedStrokeColor() : getUnSelectedStrokeColor(), getFocusedBackgroundColor(), radius);
    }

    private void setSectionDecorationSelected(boolean isSelected, boolean isReselected) {
        if (isReselected){
            return;
        }
        if (hasBackground()) {
            animateNewBackground(isSelected);
        } else {
            setBackground(isSelected ? getSelectedBackground() : getUnSelectedBackground());
        }
        itemTV.setSelected(isSelected);
        itemTV.setTextColor(isSelected ? new Color(getSelectedTextColor()) : new Color(getUnSelectedTextColor()));
    }


    private class MyEventHandler extends EventHandler {
        private final AtomicInteger index = new AtomicInteger(0);

        public MyEventHandler(EventRunner runner) throws IllegalArgumentException {
            super(runner);
        }

        @Override
        protected void processEvent(InnerEvent event) {
            super.processEvent(event);
            if (event == null) {
                return;
            }
            int eventId = event.eventId;
            if (eventId == 0x001) {
                Object object = event.object;
                if (object instanceof ColorEntity) {
                    ColorEntity colorEntity = (ColorEntity) object;
                    if (index.get() == colorEntity.fractions.length) {
                        index.set(0);
                        handler.removeEvent(eventId);
                        return;
                    }
                    processBgColor(colorEntity.startColor, colorEntity.endColor, colorEntity.fractions[index.get()]);
                    index.incrementAndGet();
                    InnerEvent event1 = InnerEvent.get(0x001, new ColorEntity(isSelected() ? getFocusedBackgroundColor() : getSelectBackgroundColor(), isSelected() ? getSelectBackgroundColor() : getUnSelectedBackgroundColor(), getSelectionAnimationDuration()));
                    handler.sendEvent(event1, colorEntity.duration / colorEntity.fractions.length);
                }
            }
        }
    }


    private MyEventHandler handler;

    private void animateNewBackground(boolean isSelected) {
        InnerEvent event = InnerEvent.get(0x001, new ColorEntity(isSelected ? getFocusedBackgroundColor() : getSelectBackgroundColor(), isSelected ? getSelectBackgroundColor() : getUnSelectedBackgroundColor(), getSelectionAnimationDuration()));
        handler = new MyEventHandler(EventRunner.getMainEventRunner());
        handler.sendEvent(event);
    }

    private void processBgColor(int startColor, int endColor, float fraction) {
        int evaluate = ArgbEvaluator.getInstance().evaluate(fraction, startColor, endColor);
        ShapeElement bg = getBackground(getStrokeWidth(), isSelected() ? getSelectedStrokeColor() : getUnSelectedStrokeColor(), evaluate, radius);
        setBackground(bg);
    }

    private void setBackground(ShapeElement drawable) {
        itemTV.setBackground(drawable);

    }

    private boolean hasBackground() {
        return itemTV.getBackgroundElement() != null;
    }
}
